package com.minis.context;

import com.minis.beans.factory.DefaultListableBeanFactory;
import com.minis.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import com.minis.beans.factory.config.BeanPostProcessor;
import com.minis.beans.exception.BeansException;
import com.minis.beans.factory.support.ConfigurableListableBeanFactory;
import com.minis.core.ClassPathXmlResource;
import com.minis.beans.factory.xml.XmlBeanDefinitionReader;

import java.util.ArrayList;
import java.util.List;

public class ClassPathXmlApplicationContext extends AbstractApplicationContext {
//    // simple
//    SimpleBeanFactory beanFactory;
//    // autowired
//    AutowiredBeanFactory beanFactory;
    DefaultListableBeanFactory beanFactory;
    private List<BeanPostProcessor> beanFactoryPostProcessors = new ArrayList<>();


    public ClassPathXmlApplicationContext(String fileName) {
        this(fileName, true);
    }

    public ClassPathXmlApplicationContext(String fileName, boolean isRefresh) {
        // 解析 Xml
        ClassPathXmlResource resource = new ClassPathXmlResource(fileName);
        // 创建 BeanFactory
//        // simple
//        SimpleBeanFactory beanFactory = new SimpleBeanFactory();
//        // autowired
//        AutowiredBeanFactory beanFactory = new AutowiredBeanFactory();
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 加载 BeanDefinition 到 BeanFactory
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        reader.loadBeanDefinitions(resource);
        this.beanFactory = beanFactory;
        if (isRefresh) {
//            // simple
//            this.beanFactory.refresh();
            // 处理属性并添加后处理器
            refresh();
        }
    }

    public ClassPathXmlApplicationContext() {
    }

    @Override
    protected void registerListeners() {
        ApplicationListener listener = new ApplicationListener();
        this.getApplicationEventPublisher().addApplicationListener(listener);
    }

    @Override
    protected void initApplicationEventPublisher() {
        SimpleApplicationPublisher publisher = new SimpleApplicationPublisher();
        this.setApplicationEventPublisher(publisher);
    }

    @Override
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory bf) {

    }

    @Override
    protected void registerBeanPostProcessors(ConfigurableListableBeanFactory bf) {
        this.beanFactory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
    }

    @Override
    protected void finishRefresh() {
        publishEvent(new ContextRefreshEvent("Context Refreshed..."));
    }

    @Override
    public ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException {
        return this.beanFactory;
    }

    @Override
    public void publishEvent(ApplicationEvent event) {
        this.getApplicationEventPublisher().publishEvent(event);
    }

    @Override
    public void addApplicationListener(ApplicationListener listener) {
        this.getApplicationEventPublisher().addApplicationListener(listener);
    }

    @Override
    public Object getBean(String beanName) throws BeansException {
        return this.beanFactory.getBean(beanName);
    }

    @Override
    public Boolean containsBean(String name) {
        return this.beanFactory.containsBean(name);
    }

    @Override
    public void registerBean(String beanName, Object obj) {
        this.beanFactory.registerBean(beanName, obj);
    }

    @Override
    public Boolean isSingleton(String name) {
        return false;
    }

    @Override
    public Boolean isPrototype(String name) {
        return false;
    }

    @Override
    public Class<?> getType(String name) {
        return null;
    }

    public void addBeanFactoryPostProcessors(BeanPostProcessor postProcessors) {
        this.beanFactoryPostProcessors.add(postProcessors);
    }

    public void refresh(){
        this.registerBeanPostProcessor(this.beanFactory);
        this.onRefresh();
    }


    private void registerBeanPostProcessor(ConfigurableListableBeanFactory beanFactory) {
        this.beanFactory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
        System.out.println("成功添加 Autowired 后处理器");
    }

    @Override
    protected void onRefresh() {
        this.beanFactory.refresh();
    }


}

